package com.sudoku.screen;

import java.util.ArrayList;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Preferences;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator.FreeTypeFontParameter;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.CheckBox;
import com.badlogic.gdx.scenes.scene2d.ui.CheckBox.CheckBoxStyle;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.ImageButton;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton.TextButtonStyle;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.sudoku.Sudoku;
import com.sudoku.background.BackgroundManager;
import com.sudoku.observer.Event;
import com.sudoku.observer.Subject;
import com.sudoku.sound.AudioManager;
import com.sudoku.utility.Constants;
import com.sudoku.utility.Locator;

public class OptionsScreen implements Screen, Constants {
	private BitmapFont textFont, titleFont, backgroundFont;
	private Stage stage;
	private ImageButton buttonBack;
	private CheckBox sound, hints, highlight, timer;
	private CheckBoxStyle checkBoxStyle;
	private Skin skin;
	private Label heading;
	private TextureAtlas atlas;
	private TextButtonStyle textButtonStyle, playStyle, exitStyle;
	private final ArrayList<TransitionEffect> effects;
	private SpriteBatch uiBatch;
	private Sudoku game;
	private BackgroundManager backgroundManager;
	private AudioManager audio;
	private Subject subject;

	public static float BUTTON_PLAY_HEIGHT = 0.55F;
	public static float HEADING_HEIGHT = 0.80F;
	public static float SERVICES_HEIGHT = 0.12F;
	public static float Y_SPACING = ACTUAL_VIRTUAL_HEIGHT * 0.13F;
	public static float Y_POS = ACTUAL_VIRTUAL_HEIGHT * 0.65F;
	public static float X_POS = ACTUAL_VIRTUAL_WIDTH * 0.10F;

	public OptionsScreen(final Sudoku game, MenuScreen menu, AudioManager audio, final Subject sub) {
		this.game = game;
		backgroundManager=menu.getBackground();
		stage = new Stage();
		stage.setViewport(Locator.getViewport());
		uiBatch = new SpriteBatch();
		this.subject=sub;
		this.audio = audio;

		FreeTypeFontGenerator generator = new FreeTypeFontGenerator(Gdx.files.internal(FONT));
		FreeTypeFontParameter param = new FreeTypeFontParameter();
		param.size = (int) (96);
		titleFont = generator.generateFont(param);

		param.size = (int) (72);
		textFont = generator.generateFont(param);

		param.size = (int) (40);
		backgroundFont = generator.generateFont(param);
		backgroundFont.setColor(new Color(0f, 0f, 0f, 0.3f));
		generator.dispose();

		atlas = new TextureAtlas(Gdx.files.internal("data/button.pack"));
		skin = new Skin(atlas);

		checkBoxStyle = new CheckBoxStyle();
		checkBoxStyle.checkboxOn = new Image(Locator.getAssets().get(CHECKED_CHECKBOX, Texture.class)).getDrawable();
		checkBoxStyle.checkboxOff = new Image(Locator.getAssets().get(UNCHECKED_CHECKBOX, Texture.class)).getDrawable();
		checkBoxStyle.font = textFont;
		checkBoxStyle.fontColor = new Color(0.5F, 0.5F, 0.5F, 1f);

		textButtonStyle = new TextButtonStyle();
		textButtonStyle.up = skin.getDrawable("button.up");
		textButtonStyle.down = skin.getDrawable("button.down");
		textButtonStyle.pressedOffsetX = 1;
		textButtonStyle.pressedOffsetY = -1;
		textButtonStyle.font = textFont;
		playStyle = new TextButtonStyle(textButtonStyle);
		playStyle.fontColor = new Color(0.5F, 0.5F, 0.5F, 1f);
		exitStyle = new TextButtonStyle(textButtonStyle);
		exitStyle.fontColor = new Color(0.5F, 0.5F, 0.5F, 1f);

		// create a transition screen
		effects = new ArrayList<TransitionEffect>();
		effects.add(new FadeOutTransitionEffect(0.5f));
		effects.add(new FadeInTransitionEffect(0.8f));

		createButtons();

		// create title
		LabelStyle headingStyle = new LabelStyle(titleFont, new Color(0.5F, 0.5F, 0.5F, 1f));
		heading = new Label("Options", headingStyle);

		heading.setPosition(X_POS, Y_POS + Y_SPACING *1.5f);

		sound.setPosition(X_POS, Y_POS);
		timer.setPosition(X_POS, Y_POS - Y_SPACING);
		highlight.setPosition(X_POS, Y_POS - (Y_SPACING * 2));
		hints.setPosition(X_POS, Y_POS - (Y_SPACING * 3));
		buttonBack.setPosition(X_POS, Y_POS - (Y_SPACING * 4.5f));

		stage.addActor(heading);
		stage.addActor(sound);
		stage.addActor(timer);
		stage.addActor(highlight);
		stage.addActor(hints);
		stage.addActor(buttonBack);

		uiBatch.setTransformMatrix(stage.getCamera().view);
		uiBatch.setProjectionMatrix(stage.getCamera().projection);
	}

	public void gotoMenuScreen() {
		MenuScreen next = game.getMenuScreen();
		next.show();
		game.setScreen(next);
	}

	@Override
	public void render(float delta) {
		Gdx.gl.glClearColor(1.0f, 1.0f, 1.0f, 1);
		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
		uiBatch.begin();
		backgroundManager.render(uiBatch, backgroundFont);
		uiBatch.end();

		backgroundManager.update(delta);
		stage.act(delta);
		stage.draw();

	}

	@Override
	public void resize(int width, int height) {
		stage.getViewport().update(width, height, true);
	}

	@Override
	public void show() {
		effects.clear();
		effects.add(new FadeOutTransitionEffect(0.5f));
		effects.add(new FadeInTransitionEffect(0.5f));
		Gdx.input.setInputProcessor(stage);
	}

	@Override
	public void hide() {
		Gdx.input.setInputProcessor(null);
	}

	private void createButtons() {
		sound = new CheckBox("   Enable sound", checkBoxStyle);
		sound.setScale(1.3f);
		sound.getImage().setScale(1.3f);
		sound.setChecked(!Locator.isMute());
		sound.addListener(new ChangeListener() {
			@Override
			public void changed(ChangeEvent event, Actor actor) {
				audio.flipMute();
				subject.notify(Event.EVENT_CLICK);
				writeSave();
			}
		});

		timer = new CheckBox("   Show timer", checkBoxStyle);
		timer.setScale(1.3f);
		timer.getImage().setScale(1.3f);
		timer.setChecked(Locator.showTimer);
		timer.addListener(new ChangeListener() {
			@Override
			public void changed(ChangeEvent event, Actor actor) {
				Locator.setShowTimer(timer.isChecked());
				subject.notify(Event.EVENT_CLICK);
				writeSave();
			}
		});

		highlight = new CheckBox("   Highlight Similar Tiles", checkBoxStyle);
		highlight.setScale(1.3f);
		highlight.getImage().setScale(1.3f);
		highlight.setChecked(Locator.highlightTiles);
		highlight.addListener(new ChangeListener() {
			@Override
			public void changed(ChangeEvent event, Actor actor) {
				Locator.setHighlightTiles(highlight.isChecked());
				subject.notify(Event.EVENT_CLICK);
				writeSave();
			}
		});

		hints = new CheckBox("   Enable Hints", checkBoxStyle);
		hints.setScale(1.3f);
		hints.getImage().setScale(1.3f);
		hints.setChecked(Locator.showHints);
		hints.addListener(new ChangeListener() {
			@Override
			public void changed(ChangeEvent event, Actor actor) {
				Locator.setShowHints(hints.isChecked());
				subject.notify(Event.EVENT_CLICK);
				writeSave();
			}
		});

		buttonBack = new ImageButton(new Image(Locator.getAssets().get(MENU_ARROW, Texture.class)).getDrawable());
		buttonBack.setScale(0.3f);
		buttonBack.getImage().setScale(0.3f);
		buttonBack.addListener(new ClickListener() {
			@Override
			public void clicked(InputEvent event, float x, float y) {
				gotoMenuScreen();
				subject.notify(Event.EVENT_CLICK);
			}
		});

	}
	
	public void writeSave(){
	    Preferences prefs = Gdx.app.getPreferences("My Preferences");
        prefs.putBoolean("mute", Locator.isMute());
        prefs.putBoolean("showTimer", Locator.showTimer);
        prefs.putBoolean("highlightTiles", Locator.highlightTiles);
        prefs.putBoolean("showHints", Locator.showHints);
        
        prefs.flush();
	}

	@Override
	public void pause() {
	}

	@Override
	public void resume() {
	}

	@Override
	public void dispose() {
		stage.dispose();
		atlas.dispose();
		skin.dispose();
	}

}
